package com.cloud.service.cityweather.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.cloud.commons.utils.weather.WeatherUtil;
import com.cloud.dao.cityweather.CityWeatherDao;
import com.cloud.model.entity.city.City;
import com.cloud.model.entity.cityweather.CityWeather;
import com.cloud.model.view.cityweather.CityWeatherView;
import com.cloud.scheduled.WeatherScheduled;
import com.cloud.service.cityweather.CityWeatherService;
import com.cloud.commons.utils.CloudCopyUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
* <b><code>CityWeatherImpl</code></b>
* <p/>
* CityWeather的具体实现
* <p/>
* <b>Creation Time:</b> 2019-10-16 14:31:05.
*
* @author ${model.author}
* @version 1.0.0
* @since cloud-spring-boot-be 1.0.0
*/
@Service
public class CityWeatherServiceImpl implements CityWeatherService {

    /**
     * The Constant LOG.
     */
    private static final Logger LOG = LoggerFactory
            .getLogger(CityWeatherServiceImpl.class);

    @Autowired
    private CityWeatherDao cityWeatherDao;

    @Override
    public CityWeatherView getEntity(long id) {
        // 获取Entity
        CityWeather cityWeather = cityWeatherDao.findById(id).orElseThrow(() -> new RuntimeException("获取不到id为：" + id + "的数据记录"));
        // 复制Dao层属性到view属性
        CityWeatherView cityWeatherView = new CityWeatherView();
        CloudCopyUtils.copyBean(cityWeather, cityWeatherView);
        return cityWeatherView;
    }

    @Override
    public long getEntitiesCount() {
        return cityWeatherDao.count();
    }

    @Override
    public List<CityWeatherView> findAll() {
        List<CityWeatherView> cityWeatherViews = new ArrayList<>();
        List<CityWeather> cityWeathers = cityWeatherDao.findAll();
        for (CityWeather cityWeather : cityWeathers){
            CityWeatherView cityWeatherView = new CityWeatherView();
            CloudCopyUtils.copyBean(cityWeather, cityWeatherView);
            cityWeatherViews.add(cityWeatherView);
        }
        return cityWeatherViews;
    }

    @Override
    public CityWeatherView saveEntity(CityWeatherView cityWeatherView)  {
        // 保存的业务逻辑
        CityWeather cityWeather = new CityWeather();
        CloudCopyUtils.copyBean(cityWeatherView, cityWeather);
        // user数据库映射传给dao进行存储
        cityWeather.setCreateTime(System.currentTimeMillis());
        cityWeather.setUpdateTime(System.currentTimeMillis());
        cityWeather.setWeight(System.currentTimeMillis());
        cityWeather.setEnabled(1);
        cityWeatherDao.save(cityWeather);
        CloudCopyUtils.copyBean(cityWeather,cityWeatherView);
        return cityWeatherView;
    }

    @Override
    public void deleteEntity(long id) {
        CityWeather cityWeather = cityWeatherDao.findById(id).orElseThrow(() -> new RuntimeException("获取不到id为：" + id + "的数据记录"));
        cityWeather.setId(id);
        cityWeatherDao.delete(cityWeather);
    }

    @Override
    @Transactional(rollbackOn = { Exception.class })
    public void deleteEntities(String ids) {
        String[] entityIds= ids.split("\\,");
        List<CityWeather> cityWeathers = new ArrayList<>();
        for(String entityId : entityIds){
            CityWeather cityWeather = new CityWeather();
            cityWeather.setId(Long.valueOf(entityId));
            cityWeathers.add(cityWeather);
        }
        cityWeatherDao.deleteInBatch(cityWeathers);
    }

    @Override
    public void updateEntity(CityWeatherView cityWeatherView) {
        Specification<CityWeather> cityWeatherSpecification = Optional.ofNullable(cityWeatherView).map( s -> {
            return new Specification<CityWeather>() {
                @Override
                public Predicate toPredicate(Root<CityWeather> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                    List<Predicate> predicates = new ArrayList<>();
                    // id
                    predicates.add(criteriaBuilder.equal(root.get("id").as(Long.class), s.getId()));

                    criteriaQuery.where(predicates.toArray(new Predicate[predicates.size()]));
                    return criteriaQuery.getRestriction();
                }
            };
        }).orElseThrow(()->new IllegalArgumentException("CityWeatherView is null"));


        // 获取原有的属性，把不变的属性覆盖
        Optional<CityWeather> cityWeatherOptionalBySearch = cityWeatherDao.findOne(cityWeatherSpecification);
        cityWeatherOptionalBySearch.map(cityWeatherBySearch -> {
            CloudCopyUtils.copyBeanExcludeNull(cityWeatherView,cityWeatherBySearch);
            cityWeatherBySearch.setUpdateTime(System.currentTimeMillis());
            cityWeatherDao.save(cityWeatherBySearch);
            return "";
        }).orElseThrow(()->new RuntimeException("无法找到id为" + cityWeatherView.getId() + "的数据记录"));
    }

    @Override
    @Transactional
    public void updateCityWeatherEntiy(City city) {
        // 目前先获取两种类型的信息，当前天气情况和未来三天天气情况
        String location = "";
        String weatherTypeNow = "now";
        location += !ObjectUtils.isEmpty(city.getArea()) ? city.getArea() + "," + city.getCity() : city.getCity();
        // 保存当前天气情况
        saveOrupdateWeatherView(city, location, weatherTypeNow);
        // 保存未来三天天气情况
        String weatherTypeForecast = "forecast";
        saveOrupdateWeatherView(city,location,weatherTypeForecast);
    }

    private void saveOrupdateWeatherView(City city, String location, String weatherTypeNow) {
        JSONObject weatherResultJson = WeatherUtil.getHeweatherResult(weatherTypeNow,location);
        CityWeather cityWeather = cityWeatherDao.findByCityIdAndWeatherType(city.getId(),weatherTypeNow);
        if (ObjectUtils.isEmpty(cityWeather)) {
            // 新建信息
            createCityWeatherView(city.getId(),weatherResultJson,weatherTypeNow);
        } else {
            // 更新信息
            updateCityWeatherView(cityWeather,weatherResultJson);
        }
    }

    private void updateCityWeatherView(CityWeather cityWeather, JSONObject weatherResultJson) {
        CityWeatherView cityWeatherView = new CityWeatherView();
        CloudCopyUtils.copyBean(cityWeather,cityWeatherView);
        cityWeatherView.setWeatherResultJson(JSON.toJSONString(weatherResultJson));
        updateEntity(cityWeatherView);
    }

    private void createCityWeatherView(Long cityId, JSONObject weatherResultJson, String weatherTypeNow) {
        CityWeatherView cityWeatherView = new CityWeatherView();
        cityWeatherView.setCityId(cityId);
        cityWeatherView.setWeatherResultJson(JSON.toJSONString(weatherResultJson));
        cityWeatherView.setWeatherType(weatherTypeNow);
        saveEntity(cityWeatherView);
    }
}
